/*****************************************************************************
* $Workfile:: nvm.c                                                         $
* $Revision:: 19                                                            $
* $JustDate::  3/21/12                                                      $
*
*      GENIE V ECU
*      simple nvm
*****************************************************************************/

#include "common.h"
#include "battery.h"
#include "eeprom.h"
#include "faults.h"
#include "fet.h"
#include "curve.h"
#include "control.h"
#include "main.h"
#include "nvm.h"
#include "load_sensing.h"

#define NVM_CYCLE   20      // 20 ms
#define NVM_RATE    ((NVM_CYCLE/SYSTEM_CYCLE) - 1 )

struct
{
   UINT8 fSetupInitFinihed: 1;
   UINT8 fSetupInit: 1;
   UINT8 fBatteryStateWrite: 1;
   UINT8 fBatteryLevelWrite: 1;
   UINT8 fTripAngleStateWrite: 1;
   UINT8 fSleepTimeStateWrite: 1;
   UINT8 fLiftDriveWrite: 1;
   UINT8 fFaultWrite: 1;
   UINT8 bGpsLockOrUnlockLiftWrite: 1;
   UINT8 bHourMeterWrite: 1;
   UINT8 wRate;
   UINT8 fOutDoorStateWrite: 1;
   UINT8 fGPS_ECULOCKLIB1_Write:1;
   UINT8 fGPS_ECULOCKLIB2_Write:1;
   UINT8 fGPS_ECULOCKLIB3_Write:1;
   UINT8 fGPS_ECULOCKLIB4_Write:1;
} NVM_Data;

struct fault NVM_Fault;

lift_options_t lift_options;
struct nvm_lift_setup lift_setup;

struct LiftDrive NVM_LiftDrive;

struct OutDoorMode NVM_OutDoorMode;

struct BatteryState NVM_BatteryState;
struct BatteryLevel NVM_BatteryLevel;


struct TripAngleState NVM_TripAngleState;
//struct nvm_timer_setup timer_setup;

struct SleepTimeState NVM_SleepTimeState;

static void setup_copy(struct nvm_lift_setup * pSetup);


/*******************************************************************************
 *
 * PROCEDURE:    SETUP_Init()
 *
 * DESCRIPTION: It copies eeprom or default if eerpom is failed to different
 *              structures.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
SETUP_Init(void)
{
   UINT8 ix;
   struct nvm_lift_setup * pSetup;

   switch(GET_LIFT_TYPE(lift_options))
   {
      default:
      case LIFT_TYPE_SMALL_SLAB:
         pSetup = (struct nvm_lift_setup *)&small_slab_setup;
         break;
      case LIFT_TYPE_ELEC1:
         pSetup = (struct nvm_lift_setup *)&electric1_setup;
         break;
    /*case LIFT_TYPE_ELEC2:
         pSetup = (struct nvm_lift_setup *)&electric2_setup;
         break;*/
      case LIFT_TYPE_ELEC3:
         pSetup = (struct nvm_lift_setup *)&electric3_setup;
         break;
   }

   for(ix = 0; ix < 5; ix++)
   {
      if(!((EEPROM_OK == record_read(pSetup->bLiftType, sizeof(struct nvm_lift_setup), (UINT8 *)&lift_setup))))
           //&& (IMAGE_Descr.szName[ 0] == lift_setup.bMajor)
           //&& (IMAGE_Descr.szName[ 1] == lift_setup.bMinor)))
      {
         setup_copy(pSetup);     // Copy over the default values.

         // for US machine, change default (only ELEC1 or ELEC3)
         if(lift_options.fUS_option && ((lift_options.fType == LIFT_TYPE_ELEC1) || (lift_options.fType == LIFT_TYPE_ELEC3)))
         {
            lift_setup.drive_rised_curve.bAccelIncrement = 6;
            lift_setup.drive_rised_curve.bDecelIncrement = 12;
            lift_setup.drive_rised_curve.bPeriod = 40;
         }
         // for Korea machine, change default
         else if(lift_options.fKorea_option)
         {
            //lift_setup.drive_rised_curve.bPwmPosAdjust = 0;
            //lift_setup.drive_rised_curve.bPwmNegAdjust = 0;
         }
      }
      else
      {
         ix = 5;
      }
   }
   CONTROL_Setup();
   CURVE_Setup();
   BATTERY_Setup();
   IN_OUT_DOOR_OPTION_Setup();
   LiftUpPressLiftButtonModeSetup();
   FET_Setup();
   
}

/*******************************************************************************
*
* PROCEDURE: NVM_LoadOptionCode()
*
* DESCRIPTION:
*   This function read the option code value from EEPROM and loads it into the
*   variable lift_options.  The option code is stored in two EEPROM data records,
*   a backup, redundant copy of the option code.
*
* RETURNS:
*         0 : Option code was loaded successfully
*  Non Zero : Option Code failed to be loaded form EEPROM.
*
* VARIABLE NAME    R/W DESCRIPTION
* ---------------- --- --------------------------------------------------------
* lift_options     W   Loads the value of the option Code.
*******************************************************************************/
UINT8
NVM_LoadOptionCode(void)
{
   UINT16 option1;
   UINT16 option2;
   UINT16 option3;
   EEPROM_ERR block1Error = record_read(RECORD_MAGIC_OPTION_1, 2, (UINT8 *)&option1);
   EEPROM_ERR block2Error = record_read(RECORD_MAGIC_OPTION_2, 2, (UINT8 *)&option2);
   EEPROM_ERR block3Error = record_read(RECORD_MAGIC_OPTION_3, 2, (UINT8 *)&option3);

   UINT8 success = 0;

   // all blocks read OK
   if((EEPROM_OK == block1Error) && (EEPROM_OK == block2Error) && (EEPROM_OK == block3Error))
   {
      // all options read OK
      if ((option1 == option2) && (option2 == option3 ))
      {
         success = 0;
      }
      // option 1 and 2 read OK
      else if(option1 == option2)
      {
         success = 3;
      }
      // option 2 and 3 read OK
      else if(option2 == option3)
      {
         success = 1;
      }
      // option 1 and 3 read OK
      else if(option1 == option3)
      {
         success = 2;
      }
      // no option read OK
      else
      {
         success = 0xFF;
      }
   }
   // block 1 and 2 read OK
   else if((EEPROM_OK == block1Error) && (EEPROM_OK == block2Error))
   {
      // option 1 and 2 read OK
      if(option1 == option2)
      {
         success = 3;
      }
      // no option read OK
      else
      {
         success = 0xFF;
      }
   }
   // block 2 and 3 read OK
   else if((EEPROM_OK == block2Error) && (EEPROM_OK == block3Error))
   {
      // option 2 and 3 read OK
      if(option2 == option3)
      {
         success = 1;
      }
      // no option read OK
      else
      {
         success = 0xFF;
      }
   }
   // block 1 and 3 read OK
   else if((EEPROM_OK == block1Error) && (EEPROM_OK == block3Error))
   {
      // option 1 and 3 read OK
      if(option1 == option3)
      {
         success = 2;
      }
      // no option read OK
      else
      {
         success = 0xFF;
      }
   }
   // no block read OK
   else
   {
      success = 0xFF;
   }

   switch(success)
   {
      case 0:
         LIFT_OPTIONS_UINT16 = option1;
         break;

      case 1:
         LIFT_OPTIONS_UINT16 = option2;
         record_write(RECORD_MAGIC_OPTION_1, 2, (UINT8 *)&option2);
         success = 0;
         break;

      case 2:
         LIFT_OPTIONS_UINT16 = option3;
         record_write(RECORD_MAGIC_OPTION_2, 2, (UINT8 *)&option3);
         success = 0;
         break;

      case 3:
         LIFT_OPTIONS_UINT16 = option1;
         record_write(RECORD_MAGIC_OPTION_3, 2, (UINT8 *)&option1);
         success = 0;
         break;

      case 0xFF:
      default:
         LIFT_OPTIONS_UINT16 = 0x7800;
         break;
   }

   // set pressure sensor type
   if((LIFT_OPTIONS_UINT16 & 0x0080) == 0x0080)
   {
      Pressure_Current_Voltage = 1;
      Iv_Switch_Current_ON;
   }
   else
   {
      Pressure_Current_Voltage = 0;
      Iv_Switch_Voltage_ON;
   }

   return success;
}

/*************************************************************************//**
* @ingroup configure
* @brief   This function read the lock value from EEPROM and loads it
*          into the variable lift_lockset.
* @param   none
* @return  none
*****************************************************************************/
void vLoadLiftLockSet_DL(void)
{
   UINT16 u16_option;
   EEPROM_ERR en_block_error;

   // read lockset from three section
   en_block_error = record_read(RECORD_MAGIC_LIFT_LOCKSET, 2, (UINT8 *)&u16_option);

   // if section is correct, use that set
   if(EEPROM_OK == en_block_error)
   {
      unLiftlocksets.word = u16_option;
   }

   //read lock or unlock lift state
   MAIN_Data.bGeneralLockLift = unLiftlocksets.bit.bGeneralLockLift;
   MAIN_Data.bFirstLockLift = unLiftlocksets.bit.bFirstLockLift;
   MAIN_Data.bSecondLockLift = unLiftlocksets.bit.bSecondLockLift;
   MAIN_Data.bLockLiftState = MAIN_Data.bFirstLockLift || MAIN_Data.bSecondLockLift || MAIN_Data.bGeneralLockLift;
}

/*******************************************************************************
 *
 * PROCEDURE: setup_copy()
 *
 * DESCRIPTION: it copies default parameters ro ram.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

static void
setup_copy(struct nvm_lift_setup * pSetup)
{
   UINT8 ix;
   UINT8 * pb;
   UINT8 * ps;

   pb = (UINT8 *)&lift_setup;
   ps = (UINT8 *)pSetup;

   // pointer checked above

   for(ix = 0; ix < sizeof(struct nvm_lift_setup); ix++)
   {
      *pb++ = *ps++;
   }

   lift_setup.bMajor =  IMAGE_Descr.szName[ 0];
   lift_setup.bMinor =  IMAGE_Descr.szName[ 1];

}

/*******************************************************************************
 *
 * PROCEDURE: NVM_ClearFaultHistory()
 *
 * DESCRIPTION: it clear faule history.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_ClearFaultHistory(void)
{
   UINT8 ix;

   for(ix = 0; ix < NVM_FAULT_RECORD_SIZE; ix++)
   {
      NVM_Fault.abData[ ix] = 0;
   }
   NVM_Fault.bNewFaultCount = 0;
   NVM_Data.fFaultWrite = 1;
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveFault()
 *
 * DESCRIPTION: it saves faule history.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_SaveFault(UINT16 wFault)
{
   UINT8 ix;
   UINT8 bFault;

   bFault = wFault & 0x7F;

   if(wFault
         && !( FAULT_COM_ERROR == wFault
              || FAULT_POTHOLE_GUARD_FAILURE == wFault))
   {
      NVM_Fault.wLastFault = wFault;
   }

   if(!bFault
      || NVM_Fault.abData[0] == bFault)
   {
      return;
   }
   //psuedo stack
   for(ix = (NVM_FAULT_RECORD_SIZE - 1); ix > 0 ; ix--)
   {
      NVM_Fault.abData[ ix] = NVM_Fault.abData[ ix - 1];
   }

   NVM_Fault.abData[0] = bFault;
   if(NVM_Fault.bNewFaultCount < NVM_FAULT_RECORD_SIZE)
   {
      NVM_Fault.bNewFaultCount++;
   }
   NVM_Data.fFaultWrite = 1;
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveMotorCtlrFault()
 *
 * DESCRIPTION: Flags the fault as a motor controller fault and saves
 *              to the fault to the fault history.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/
void
NVM_SaveMotorCtlrFault(UINT16 wFault)
{
#ifdef SHOW_MOTOR_CTLR_SOURCE_FAULT
   NVM_SaveFault(wFault | MOTOR_FAULT_FLAG);
#else
   NVM_SaveFault(wFault);
#endif
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_InitFault()
 *
 * DESCRIPTION: it initializes faule history.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_InitFault(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_FAULT
                               , NVM_FAULT_RECORD_SIZE
                               , (UINT8 *)&NVM_Fault.abData[ 0]))
   {
      NVM_ClearFaultHistory();
   }
}


/*******************************************************************************
 *
 * PROCEDURE: NVM_InitLiftDrive()
 *
 * DESCRIPTION: it initializes LiftDrie state variable
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_InitLiftDrive(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_LIFT_DRIVE
                               , 1
                               , (UINT8 *)&NVM_LiftDrive.bData))
   {
      NVM_LiftDrive.bData = 0;
   }
}

void
NVM_InitOutDoorMode(void)
{
	if(EEPROM_OK != record_read(RECORD_MAGIC_OUTDOOR_MODE
								, 1
								, (UINT8 *)&NVM_OutDoorMode.bData))
	{
		NVM_OutDoorMode.bData = 0;
	}
	MAIN_Data.bOutDoorMode = NVM_OutDoorMode.bData;
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveLiftDrive()
 *
 * DESCRIPTION: it saves LiftDrie state variable
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_SaveLiftDrive(UINT8 bData)
{
   if(bData != NVM_LiftDrive.bData)
   {
      NVM_LiftDrive.bData = bData;
      NVM_Data.fLiftDriveWrite = 1;
   }
}

void
NVM_SaveOutDoorMode(UINT8 bData)
{
	if(bData != NVM_OutDoorMode.bData)
	{
		NVM_OutDoorMode.bData = bData;
		NVM_Data.fOutDoorStateWrite = 1;
	}
}
/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveBatteryState()
 *
 * DESCRIPTION: it saves LiftDrie state variable
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/
void NVM_SaveBatteryLevel(UINT8 nData)
{
   NVM_BatteryLevel.bData = nData;
   NVM_Data.fBatteryLevelWrite = 1;
}
void NVM_InitBatteryLevel(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_BATTERY_Level,
                               1,
                               (UINT8 *)&NVM_BatteryLevel.bData))
   {
      NVM_BatteryLevel.bData = 0;
   }
}
UINT8 NVM_GetBatteryLevel(void)
{
   return NVM_BatteryLevel.bData;
}

//
void
NVM_SaveBatteryState(INT16 nData)
{
   NVM_BatteryState.nData = nData;
   NVM_Data.fBatteryStateWrite = 1;
}

INT16
NVM_GetBatteryState(void)
{
   return NVM_BatteryState.nData;
}

void NVM_InitBatteryState(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_BATTERY,
                               sizeof(NVM_BatteryState.nData),
                               (UINT8 *)&NVM_BatteryState.nData))
   {
      NVM_BatteryState.nData = -1;
   }
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveTripAngle()
 *
 * DESCRIPTION: it saves angle sensor down limit trip angle
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_SaveTripAngleState(UINT8 bx, UINT16 nData)
{
   if(bx < NVM_ANGLE_RECORD_SIZE)
   {
      NVM_TripAngleState.anData[ bx] = nData;
      NVM_Data.fTripAngleStateWrite = 1;
   }
}

UINT16
NVM_GetTripAngleState(UINT8 bx)
{
   if (bx == POTHOLE_ANGLE)
   {
      if (MAIN_Data.fAnglePolarity)
      {
         return (NVM_TripAngleState.anData[DOWN_LIMIT_ANGLE] + 10);
      }
      else
      {
         return (NVM_TripAngleState.anData[DOWN_LIMIT_ANGLE] - 10);
      }
   }
   else if (bx != DESCENT_ANGLE_DIFF)
   {
   		return NVM_TripAngleState.anData[ bx];
   }
   else
   {
      if (MAIN_Data.fAnglePolarity)
      {
         return (NVM_TripAngleState.anData[DOWN_LIMIT_ANGLE] + NVM_TripAngleState.anData[DESCENT_ANGLE_DIFF]);
      }
      else
      {
         return (NVM_TripAngleState.anData[DOWN_LIMIT_ANGLE] - NVM_TripAngleState.anData[DESCENT_ANGLE_DIFF]);
      }
   }
}

void NVM_InitTripAngleState(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_TRIP_ANGLE
                               , (NVM_ANGLE_RECORD_SIZE * 2)
                               , (UINT8 *)&NVM_TripAngleState.anData[ 0]))
   {
      UINT8 bx;

      for(bx = 0; bx < NVM_ANGLE_RECORD_SIZE; bx++)
      {
         NVM_TripAngleState.anData[ bx] = 0;
         NVM_TripAngleState.anData[DESCENT_ANGLE_DIFF] = 12;
      }
   }
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveSleepTimerState()
 *
 * DESCRIPTION: it saves Sleep timer and battery drain timer
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_SaveSleepTimerState(UINT8 bx, UINT8 bData)
{
   if(bx < NVM_TIME_RECORD_SIZE)
   {
      NVM_SleepTimeState.bData[ bx] = bData;
      NVM_Data.fSleepTimeStateWrite = 1;
   }
}

UINT8
NVM_GetSleepTimerState(UINT8 bx)
{
   return ((UINT8)(NVM_SleepTimeState.bData[ bx]));
}

void
NVM_SaveHourMeter(void)
{
   NVM_Data.bHourMeterWrite = 1;
}

void
NVM_SaveGpsLockOrUnlockLift(void)
{
   NVM_Data.bGpsLockOrUnlockLiftWrite = TRUE;
}


void NVM_InitSleepTimeState(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_TIME
                               , (NVM_TIME_RECORD_SIZE)
                               , (UINT8 *)&NVM_SleepTimeState.bData[ 0]))
   {
      UINT8 bx;

      for(bx = 0; bx < NVM_TIME_RECORD_SIZE; bx++)
      {
         NVM_SleepTimeState.bData[ bx] = 0;
      }
   }
}

void NVM_InitHourMeter(void)
{
   if(EEPROM_OK != record_read(RECORD_MAGIC_HOURMETER,
                               12,
                               (UINT8 *)&stHourMeter))
   {
      stHourMeter.u32Fraction = 0;
     stHourMeter.u32FractionOld = 0;
     stHourMeter.u32FractionSave = 0;
   }
}
/*******************************************************************************
 *
 * PROCEDURE: NVM_SaveHeightTime()
 *
 * DESCRIPTION: it saves HeightTime state variable
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_SetupInit(void)
{
   NVM_Data.fSetupInit = 1;
}

UINT8
NVM_CheckSetupInit(void)
{
   return ((NVM_Data.fSetupInitFinihed) ? 1 : 0);
}

/*******************************************************************************
 *
 * PROCEDURE: NVM_Task()
 *
 * DESCRIPTION: it saves LiftDrie state variable and Falut history in eeprom.
 *              It calles once per system cycle.
 *
 * VARIABLE NAME    R/W DESCRIPTION
 * ---------------- --- --------------------------------------------------------
 ******************************************************************************/

void
NVM_Task(void)
{
   if(NVM_Data.wRate)
   {
      NVM_Data.wRate--;
   }
   else
   {
      NVM_Data.wRate = NVM_RATE;

      if(NVM_Data.fSetupInit && !NVM_Data.fSetupInitFinihed)
      {
         SETUP_Init();
		 vECULockLib_Init();
		 vLoadLiftLockSet_DL();
         NVM_Data.fSetupInit = 0;
         NVM_Data.fSetupInitFinihed = 1;
      }
      else if(NVM_Data.fLiftDriveWrite)
      {
         record_write(RECORD_MAGIC_LIFT_DRIVE
                      , 1
                      , (UINT8 *)&NVM_LiftDrive.bData);
         NVM_Data.fLiftDriveWrite = 0;
      }
	  else if(NVM_Data.fOutDoorStateWrite)
      {
		  record_write(RECORD_MAGIC_OUTDOOR_MODE
					   , 1
					   , (UINT8 *)&NVM_OutDoorMode.bData);
		  NVM_Data.fOutDoorStateWrite = 0;
      }
      else if(NVM_Data.fFaultWrite)
      {
         record_write(RECORD_MAGIC_FAULT
                      , NVM_FAULT_RECORD_SIZE
                      , (UINT8 *)&NVM_Fault.abData[ 0]);
         NVM_Data.fFaultWrite = 0;
      }
      else if(NVM_Data.fBatteryStateWrite)
      {
         record_write(RECORD_MAGIC_BATTERY,
                      sizeof(NVM_BatteryState.nData),
                      (UINT8 *)&NVM_BatteryState.nData);
         NVM_Data.fBatteryStateWrite = 0;
      }
	  else if(NVM_Data.fBatteryLevelWrite)
	  {
		  record_write(RECORD_MAGIC_BATTERY_Level,
	                      1,
	                      (UINT8 *)&NVM_BatteryLevel.bData);
		NVM_Data.fBatteryLevelWrite = 0;
	  }
      else if(NVM_Data.fTripAngleStateWrite)
      {
         record_write(RECORD_MAGIC_TRIP_ANGLE
                      , (NVM_ANGLE_RECORD_SIZE * 2)
                      , (UINT8 *)&NVM_TripAngleState.anData[ 0]);
         NVM_Data.fTripAngleStateWrite = 0;
      }
      else if(NVM_Data.fSleepTimeStateWrite)
      {
         if(!record_write(RECORD_MAGIC_TIME
                          , (NVM_TIME_RECORD_SIZE)
                          , (UINT8 *)&NVM_SleepTimeState.bData[ 0]))
            NVM_Data.fSleepTimeStateWrite = 0;
      }
     else if(NVM_Data.fSleepTimeStateWrite)
      {
         if(!record_write(RECORD_MAGIC_TIME
                          , (NVM_TIME_RECORD_SIZE)
                          , (UINT8 *)&NVM_SleepTimeState.bData[ 0]))
            NVM_Data.fSleepTimeStateWrite = 0;
      }
     else if(NVM_Data.bGpsLockOrUnlockLiftWrite)
      {
         if(!record_write(RECORD_MAGIC_LIFT_LOCKSET
                          , (2)
                          , (UINT8 *)&unLiftlocksets))
            NVM_Data.bGpsLockOrUnlockLiftWrite = 0;
      }
     else if(NVM_Data.bHourMeterWrite)
      {
         if(!record_write(RECORD_MAGIC_HOURMETER
                          , (12)
                          , (UINT8 *)&stHourMeter))
            NVM_Data.bHourMeterWrite = 0;
      }
	 else if(NVM_Data.fGPS_ECULOCKLIB1_Write)
	 {
		if(!record_write(RECORD_MAGIC_ECULOCKLIB_DATA1
                          , (48)
                          , (UINT8 *)&stECULockLibStored.u8LockLibData[0]))
            NVM_Data.fGPS_ECULOCKLIB1_Write = 0;
	 }
	 else if(NVM_Data.fGPS_ECULOCKLIB2_Write)
	 {
		if(!record_write(RECORD_MAGIC_ECULOCKLIB_DATA2
                          , (48)
                          , (UINT8 *)&stECULockLibStored.u8LockLibData[0]))
            NVM_Data.fGPS_ECULOCKLIB2_Write = 0;
	 }
	 else if(NVM_Data.fGPS_ECULOCKLIB3_Write)
	 {
		if(!record_write(RECORD_MAGIC_ECULOCKLIB_DATA3
                          , (48)
                          , (UINT8 *)&stECULockLibStored.u8LockLibData[0]))
            NVM_Data.fGPS_ECULOCKLIB3_Write = 0;
	 }
	 else if(NVM_Data.fGPS_ECULOCKLIB4_Write)
	 {
		if(!record_write(RECORD_MAGIC_ECULOCKLIB_DATA4
                          , (48)
                          , (UINT8 *)&stECULockLibStored.u8LockLibData[0]))
            NVM_Data.fGPS_ECULOCKLIB4_Write = 0;
	 }
   }
}



void NVM_SaveGPS_ECULOCKLIB(void)
{
	NVM_Data.fGPS_ECULOCKLIB1_Write = 1;
	NVM_Data.fGPS_ECULOCKLIB2_Write = 1;
	NVM_Data.fGPS_ECULOCKLIB3_Write = 1;
	NVM_Data.fGPS_ECULOCKLIB4_Write = 1;
}
UINT8 u8Is_NVM_SaveGPS_ECULOCKLIB_Writed(void)
{
	UINT8 cnt=0;
	UINT8 ret=0;
	cnt = 0;
	if(NVM_Data.fGPS_ECULOCKLIB1_Write == 0)
	{
		cnt++;
	}
	if(NVM_Data.fGPS_ECULOCKLIB2_Write == 0)
	{
		cnt++;
	}
	if(NVM_Data.fGPS_ECULOCKLIB3_Write == 0)
	{
		cnt++;
	}
	if(NVM_Data.fGPS_ECULOCKLIB4_Write == 0)
	{
		cnt++;
	}
	if(cnt>=2)
	{
		ret = 0;
	}
	else
	{
		ret = 1;
	}
	return ret;
}
void
NVM_SaveGPSLockState(void)
{
   NVM_Data.bGpsLockOrUnlockLiftWrite = 1;
}
